package com.taikang.t.service.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.ConfigAttributeEditor;
import org.springframework.security.intercept.web.FilterInvocation;
import org.springframework.security.intercept.web.FilterInvocationDefinitionSource;
import org.springframework.security.util.AntUrlPathMatcher;
import org.springframework.security.util.RegexUrlPathMatcher;
import org.springframework.security.util.UrlMatcher;

import com.taikang.t.service.security.service.SecurityManagerSupport;

public class MySecureResourceFilter implements FilterInvocationDefinitionSource, InitializingBean {
	private Logger log = Logger.getLogger(MySecureResourceFilter.class);
	private UrlMatcher urlMatcher;

	private boolean useAntPath = true;
	private boolean lowercaseComparisons = true;

	public void setUseAntPath(boolean useAntPath) {
		this.useAntPath = useAntPath;
	}

	/**
	 * @param lowercaseComparisons
	 */
	public void setLowercaseComparisons(boolean lowercaseComparisons) {
		this.lowercaseComparisons = lowercaseComparisons;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	public void afterPropertiesSet() throws Exception {

		// default url matcher will be RegexUrlPathMatcher
		this.urlMatcher = new RegexUrlPathMatcher();

		if (useAntPath) { // change the implementation if required
			this.urlMatcher = new AntUrlPathMatcher();
		}

		// Only change from the defaults if the attribute has been set
		if ("true".equals(lowercaseComparisons)) {
			if (!this.useAntPath) {
				((RegexUrlPathMatcher) this.urlMatcher).setRequiresLowerCaseUrl(true);
			}
		} else if ("false".equals(lowercaseComparisons)) {
			if (this.useAntPath) {
				((AntUrlPathMatcher) this.urlMatcher).setRequiresLowerCaseUrl(false);
			}
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.intercept.ObjectDefinitionSource#getAttributes(java.lang.Object)
	 */
	public ConfigAttributeDefinition getAttributes(Object filter) throws IllegalArgumentException {

		FilterInvocation filterInvocation = (FilterInvocation) filter;
		String requestURI = filterInvocation.getRequestUrl();

		Map<String, String> urlAuthorities = securityManagerSupport.loadUrlAuthorities();

		List<String> rolesList = new ArrayList<String>();

		for (Iterator<Map.Entry<String, String>> iter = urlAuthorities.entrySet().iterator(); iter.hasNext();) {
			Map.Entry<String, String> entry = iter.next();
			String url = entry.getKey();
//			log.debug(requestURI + " urlMatcher? " + url);
			if (urlMatcher.pathMatchesUrl(url, requestURI)) {

				log.debug(requestURI + " urlMatcher :) " + url);
				String grantedAuthorities = entry.getValue();
				rolesList.add(grantedAuthorities);
				log.debug(requestURI + " urlMatcher :) " + url + "ROLE_NAME=" + grantedAuthorities);
				break;
			}

		}
		if (rolesList.size() == 0) {
			log.debug("URL没有赋给任何用户，给他增加form认证的基本角色ROLE_USER。");
			rolesList.add("ROLE_USER");
		}
		String allRoles = StringUtils.join(rolesList, ",");
		log.debug("URL"+requestURI+"拥有的角色为："+allRoles);

		ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();
		configAttrEditor.setAsText(allRoles);
		return (ConfigAttributeDefinition) configAttrEditor.getValue();

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.intercept.ObjectDefinitionSource#getConfigAttributeDefinitions()
	 */
	@SuppressWarnings("unchecked")
	public Collection getConfigAttributeDefinitions() {
		return null;
		
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.intercept.ObjectDefinitionSource#supports(java.lang.Class)
	 */
	@SuppressWarnings("unchecked")
	public boolean supports(Class clazz) {
		return true;
	}

	private com.taikang.t.service.security.service.SecurityManagerSupport securityManagerSupport;

	public void setSecurityManagerSupport(SecurityManagerSupport securityManagerSupport) {
		this.securityManagerSupport = securityManagerSupport;
	}

}
